//Name : Chen Xu
//ID   : X287284
//Email: xu.c@icloud.com



//#ifdef __APPLE__      //unix
//#include <OpenGL/gl.h>
//#include <OpenGL/glu.h>
//#include <GLUT/glut.h>
//#else
//#ifdef _WIN32         //windows
//#include <windows.h>
//#endif
//#include <GL/gl.h>    // linux
//#include <GL/glu.h>
//#include <GL/glut.h>
//#endif

#include <cstdlib>
#include <cmath>
#include <iostream>
#include <fstream>
#include <string.h>
#include "MyOpengl.h"
using namespace std;

#define pi acos(-1.0)
#define DISPLAYMODE 1
static float c=M_PI/180.0f;         //弧度和角度转换参数
static int du=90,oldmy=-1,oldmx=-1; //du是视点绕y轴的角度,opengl里默认y轴是上方向
static float r=50;                  //r是视点绕y轴的半径,h是视点高度即在y轴上的坐标
static GLuint texName;

typedef struct
{
     GLubyte *imageData;//图像数据
     GLuint bpp;//像素深度
     GLuint width;//图像宽度
     GLuint height;//图像高度
     GLuint texID;//对应的纹理ID
}TextureImage;

//读取图像文件
TextureImage tex ;

int g_width;
int g_height;
float barrel=1;
float ex = 0, ey = 0 , ez = 1000 , rad=15;
float rs=.01, ang=pi/2;
double outRadius = 1, innerRadius =0.5;
double thick = 0.25;
//movement
double clockwise = 0, counterclockwise = 0;
double movex = 0, movez = 0;
//count for number
int numcount = 0;
void cube(GLfloat a,GLfloat b ,GLfloat c);
void mycube(int x,int y,int z,GLfloat size);
void cubeWithString(double x,double y,double z,char a,char b,char c,char d);
void draw3DCurve(double outRadius,double innerRadius,double thick,double start_angle,double end_angle,double delta_angle);
void draw3Dcircle(double radius,double thick);

void draw_char(char c);
void draw1();
void draw2();
void draw3();
void draw4();
void draw5();
void draw6();
void draw7();
void draw8();
void draw9();
void draw0();
void drawA();
void drawC();
void drawX();

#pragma mark draw shapes

///////////////////////////////////////////////////////////////////////////////
// draw 1: immediate mode
// 78 calls = 36 glVertex*() calls + 36 glColor*() calls + 6 glNormal*() calls
///////////////////////////////////////////////////////////////////////////////
void cubeWithTexture()
{
     glPushMatrix();
     
     glEnable(GL_TEXTURE_2D);
     
     if (DISPLAYMODE == 0) {
          glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
     }
     else if (DISPLAYMODE == 1){
          glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
     }
     glBindTexture(GL_TEXTURE_2D,tex.texID);
     
     glBegin(GL_QUADS);
     // Front Face
     glNormal3f(0,0,1);
     
     // Bottom Left Of The Texture and Quad
     glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);
     // Bottom Right Of The Texture and Quad
     glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);
     // Top Right Of The Texture and Quad
     glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f);
     // Top Left Of The Texture and Quad
     glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f);
     glEnd();
     
     glBindTexture(GL_TEXTURE_2D,tex.texID);
     glBegin(GL_QUADS);
     
     // Back Face
     glNormal3f(0,0,-1);
     
     // Bottom Right Of The Texture and Quad
     glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
     // Top Right Of The Texture and Quad
     glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);
     // Top Left Of The Texture and Quad
     glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);
     // Bottom Left Of The Texture and Quad
     glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
     glEnd();
     
     glBindTexture(GL_TEXTURE_2D,tex.texID);
     glBegin(GL_QUADS);
     // Top Face
     glNormal3f(0,-1,0);
     // Top Left Of The Texture and Quad
     glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);
     // Bottom Left Of The Texture and Quad
     glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,  1.0f,  1.0f);
     // Bottom Right Of The Texture and Quad
     glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,  1.0f,  1.0f);
     // Top Right Of The Texture and Quad
     glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);
     glEnd();
     
     glBindTexture(GL_TEXTURE_2D,tex.texID);
     glBegin(GL_QUADS);
     // Bottom Face
     glNormal3f(0,-1,0);
     // Top Right Of The Texture and Quad
     glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
     // Top Left Of The Texture and Quad
     glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
     // Bottom Left Of The Texture and Quad
     glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);
     // Bottom Right Of The Texture and Quad
     glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);
     glEnd();
     
     glBindTexture(GL_TEXTURE_2D,tex.texID);
     glBegin(GL_QUADS);
     // Right face
     glNormal3f(1,0,0);
     // Bottom Right Of The Texture and Quad
     glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
     // Top Right Of The Texture and Quad
     glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);
     // Top Left Of The Texture and Quad
     glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f);
     // Bottom Left Of The Texture and Quad
     glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);
     glEnd();
     
     glBindTexture(GL_TEXTURE_2D,tex.texID);
     glBegin(GL_QUADS);
     // Left Face
     glNormal3f(-1,0,0);
     // Bottom Left Of The Texture and Quad
     glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
     // Bottom Right Of The Texture and Quad
     glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);
     // Top Right Of The Texture and Quad
     glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f);
     // Top Left Of The Texture and Quad
     glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);
     glEnd();
     
     glDisable(GL_TEXTURE_2D);
     glPopMatrix();
}

// a cube can define edge length
void cube(GLfloat a,GLfloat b,GLfloat c){
     glPushMatrix();
     
     glScaled(a, b, c);
     cubeWithTexture();
     glPopMatrix();
}



//void cube(GLfloat a,GLfloat b,GLfloat c)
//{
//     
//     GLfloat vertices1[] =
//     { a, b, c,  -a, b, c,  -a,-b, c,      // v0-v1-v2 (front)
//          -a,-b, c,   a,-b, c,   a, b, c,      // v2-v3-v0
//          
//          a, b, c,   a,-b, c,   a,-b,-c,      // v0-v3-v4 (right)
//          a,-b,-c,   a, b,-c,   a, b, c,      // v4-v5-v0
//          
//          a, b, c,   a, b,-c,  -a, b,-c,      // v0-v5-v6 (top)
//          -a, b,-c,  -a, b, c,   a, b, c,      // v6-v1-v0
//          
//          -a, b, c,  -a, b,-c,  -a,-b,-c,      // v1-v6-v7 (left)
//          -a,-b,-c,  -a,-b, c,  -a, b, c,      // v7-v2-v1
//          
//          -a,-b,-c,   a,-b,-c,   a,-b, c,      // v7-v4-v3 (bottom)
//          a,-b, c,  -a,-b, c,  -a,-b,-c,      // v3-v2-v7
//          
//          a,-b,-c,  -a,-b,-c,  -a, b,-c,      // v4-v7-v6 (back)
//          -a, b,-c,   a, b,-c,   a,-b,-c };    // v6-v5-v4
//     
//     // normal array
//     GLfloat normals1[]  =
//     { 0, 0, 1,   0, 0, 1,   0, 0, 1,      // v0-v1-v2 (front)
//          0, 0, 1,   0, 0, 1,   0, 0, 1,      // v2-v3-v0
//          
//          1, 0, 0,   1, 0, 0,   1, 0, 0,      // v0-v3-v4 (right)
//          1, 0, 0,   1, 0, 0,   1, 0, 0,      // v4-v5-v0
//          
//          0, 1, 0,   0, 1, 0,   0, 1, 0,      // v0-v5-v6 (top)
//          0, 1, 0,   0, 1, 0,   0, 1, 0,      // v6-v1-v0
//          
//          -1, 0, 0,  -1, 0, 0,  -1, 0, 0,      // v1-v6-v7 (left)
//          -1, 0, 0,  -1, 0, 0,  -1, 0, 0,      // v7-v2-v1
//          
//          0,-1, 0,   0,-1, 0,   0,-1, 0,      // v7-v4-v3 (bottom)
//          0,-1, 0,   0,-1, 0,   0,-1, 0,      // v3-v2-v7
//          
//          0, 0,-1,   0, 0,-1,   0, 0,-1,      // v4-v7-v6 (back)
//          0, 0,-1,   0, 0,-1,   0, 0,-1 };    // v6-v5-v4
//     
//     // color array
//     GLfloat colors1[]   =
//     { 1, 1, 1,   1, 1, 0,   1, 0, 0,      // v0-v1-v2 (front)
//          1, 0, 0,   1, 0, 1,   1, 1, 1,      // v2-v3-v0
//          
//          1, 1, 1,   1, 0, 1,   0, 0, 1,      // v0-v3-v4 (right)
//          0, 0, 1,   0, 1, 1,   1, 1, 1,      // v4-v5-v0
//          
//          1, 1, 1,   0, 1, 1,   0, 1, 0,      // v0-v5-v6 (top)
//          0, 1, 0,   1, 1, 0,   1, 1, 1,      // v6-v1-v0
//          
//          1, 1, 0,   0, 1, 0,   0, 0, 0,      // v1-v6-v7 (left)
//          0, 0, 0,   1, 0, 0,   1, 1, 0,      // v7-v2-v1
//          
//          0, 0, 0,   0, 0, 1,   1, 0, 1,      // v7-v4-v3 (bottom)
//          1, 0, 1,   1, 0, 0,   0, 0, 0,      // v3-v2-v7
//          
//          0, 0, 1,   0, 0, 0,   0, 1, 0,      // v4-v7-v6 (back)
//          0, 1, 0,   0, 1, 1,   0, 0, 1 };    // v6-v5-v4
//     
//     if (DISPLAYMODE == 0) {
//          glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
//     }
//     else if (DISPLAYMODE == 1){
//          glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
//     }
//     
//     // enble and specify pointers to vertex arrays
//     glEnableClientState(GL_NORMAL_ARRAY);
//     //glEnableClientState(GL_COLOR_ARRAY);
//     glEnableClientState(GL_VERTEX_ARRAY);
//     
//     glNormalPointer(GL_FLOAT, 0, normals1);
//     // glColorPointer(3, GL_FLOAT, 0, colors1);
//     glVertexPointer(3, GL_FLOAT, 0, vertices1);
//     glPushMatrix();
//     
//     glDrawArrays(GL_TRIANGLES, 0, 36);
//     
//     glPopMatrix();
//     
//     
//     glDisableClientState(GL_VERTEX_ARRAY);  // disable vertex arrays
//     // glDisableClientState(GL_COLOR_ARRAY);
//     glDisableClientState(GL_NORMAL_ARRAY);
//     
//     std::cout << "cube";
//}


//cube with protruding eaves
void mycube(int x,int y,int z,GLfloat size){
     float divide = 7;
     glPushMatrix();
     glTranslatef(x,y,z);
     
     
     glPushMatrix();
     glColor3f(1, 1, 1);
     
     glScaled(size, size, size);
     cubeWithTexture();
     glPopMatrix();
     
     
     //right
     glPushMatrix();
     glTranslatef(size*(1+1/divide),size*(1+1/divide),0);
     cube(size/divide, size/divide, size*(1+2/divide));
     glPopMatrix();
     
     glPushMatrix();
     glTranslatef(size*(1+1/divide),-size*(1+1/divide),0);
     cube(size/divide, size/divide, size*(1+2/divide));
     glPopMatrix();
     
     glPushMatrix();
     glTranslatef(size*(1+1/divide),0,-size*(1+1/divide));
     cube(size/divide, size*(1+2/divide), size/divide);
     glPopMatrix();
     
     glPushMatrix();
     glTranslatef(size*(1+1/divide),0,size*(1+1/divide));
     cube(size/divide, size*(1+2/divide), size/divide);
     glPopMatrix();
     
     
     //front back
     glPushMatrix();
     glTranslatef(0,size*(1+1/divide),-size*(1+1/divide));
     cube(size*(1+2/divide),size/divide,size/divide);
     glPopMatrix();
     
     glPushMatrix();
     glTranslatef(0,size*(1+1/divide),size*(1+1/divide));
     cube(size*(1+2/divide),size/divide, size/divide);
     glPopMatrix();
     
     glPushMatrix();
     glTranslatef(0,-size*(1+1/divide),-size*(1+1/divide));
     cube(size*(1+2/divide),size/divide,size/divide);
     glPopMatrix();
     
     glPushMatrix();
     glTranslatef(0,-size*(1+1/divide),size*(1+1/divide));
     cube(size*(1+2/divide),size/divide, size/divide);
     glPopMatrix();
     
     //left
     glPushMatrix();
     glTranslatef(-size*(1+1/divide),size*(1+1/divide),0);
     cube(size/divide, size/divide, size*(1+2/divide));
     glPopMatrix();
     
     glPushMatrix();
     glTranslatef(-size*(1+1/divide),-size*(1+1/divide),0);
     cube(size/divide, size/divide, size*(1+2/divide));
     glPopMatrix();
     
     glPushMatrix();
     glTranslatef(-size*(1+1/divide),0,-size*(1+1/divide));
     cube(size/divide, size*(1+2/divide), size/divide);
     glPopMatrix();
     
     glPushMatrix();
     glTranslatef(-size*(1+1/divide),0,size*(1+1/divide));
     cube(size/divide, size*(1+2/divide), size/divide);
     glPopMatrix();
     
     
     glPopMatrix();
}

void cubeWithString(double x,double y,double z,char a,char b,char c,char d){
     glPushMatrix();
     
     double size = 2;
     int divide = 7;
     //put front char
     glPushMatrix();
     glTranslatef(x, y, z+size*(1+1/divide));
     draw_char(a);
     glPopMatrix();
     
     //put left char
     glPushMatrix();
     glTranslatef(x-size*(1+1/divide), y, z);
     glRotated(270, 0, 1, 0);
     draw_char(b);
     glPopMatrix();
     
     //put back char
     glPushMatrix();
     glTranslatef(x, y, z-size*(1+1/divide));
     glRotated(180, 0, 1, 0);
     draw_char(c);
     glPopMatrix();
     
     //put right char
     glPushMatrix();
     glTranslatef(x+size*(1+1/divide), y, z);
     glRotated(90, 0, 1, 0);
     draw_char(d);
     glPopMatrix();
     
     //put top char
     glPushMatrix();
     glTranslatef(x, y+size*(1+1/divide), z);
     glRotated(270, 1, 0, 0);
     draw_char(d);
     glPopMatrix();
     
     //put down char
     glPushMatrix();
     glTranslatef(x, y-size*(1+1/divide), z);
     glRotated(270, 1, 0, 0);
     draw_char(d);
     glPopMatrix();
     
     mycube(x, y, z, size);
     
     glPopMatrix();
}

void draw3DCurve(double outRadius,double innerRadius,double thick,double start_angle,double end_angle,double delta_angle){
     
     
     double tempRadius;
     double centerx = 0;
     double centery = 0;
     bool odd = false;
     
     glEnable(GL_CULL_FACE);
     
     if (DISPLAYMODE == 0) {
          glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
     }
     else if (DISPLAYMODE == 1){
          glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
     }
     
     
     //front face
     glBegin(GL_TRIANGLE_STRIP);
     glNormal3f(0,0,1);
     for (double i=end_angle;i>=start_angle;i-=delta_angle)
     {
          tempRadius = odd ? innerRadius:outRadius;
          double vx= centerx + tempRadius * cos(i);
          double vy= centery + tempRadius * sin(i);
          double vz= thick;
          glVertex3f(vx,vy,vz);
          odd = !odd;
     }
     glEnd();
     
     odd = false;
     //back face
     glBegin(GL_TRIANGLE_STRIP);
     glNormal3f(0,0,-1);
     for (double i=start_angle;i<=end_angle;i+=delta_angle)
     {
          tempRadius = odd ? innerRadius:outRadius;
          double vx= centerx + tempRadius * cos(i);
          double vy= centery + tempRadius * sin(i);
          double vz= -thick;
          glVertex3f(vx,vy,vz);
          odd = !odd;
     }
     glEnd();
     
     //middle outline
     odd = false;
     glBegin(GL_TRIANGLE_STRIP);
     tempRadius = outRadius;
     for (double i=end_angle;i>=start_angle;i-=delta_angle)
     {
          double vx= centerx + tempRadius * cos(i);
          double vy= centery + tempRadius * sin(i);
          double vz= odd? thick:-thick;
          glNormal3f(vx/sqrt(vx*vx+vy*vy),vy/sqrt(vx*vx+vy*vy),0);
          glVertex3f(vx,vy,vz);
          odd = !odd;
     }
     glEnd();
     
     //middle innerline
     odd = false;
     glBegin(GL_TRIANGLE_STRIP);
     tempRadius = innerRadius;
     for (double i=start_angle;i<=end_angle;i+=delta_angle)
     {
          double vx= centerx + tempRadius * cos(i);
          double vy= centery + tempRadius * sin(i);
          double vz= odd? thick:-thick;
          glNormal3f(-vx/sqrt(vx*vx+vy*vy),-vy/sqrt(vx*vx+vy*vy),0);
          glVertex3f(vx,vy,vz);
          odd = !odd;
     }
     glEnd();
     
     
     //--------draw square--------
     //bottom square
     double vx,vy,vz;
     
     glBegin(GL_TRIANGLE_STRIP);
     
     tempRadius = innerRadius;
     vx= tempRadius * cos(start_angle);
     vy= centery+tempRadius * sin(start_angle);
     vz= -thick;
     glVertex3f(vx,vy,vz);
     
     tempRadius = outRadius;
     vx= tempRadius * cos(start_angle);
     vy= centery+tempRadius * sin(start_angle);
     vz= -thick;
     glVertex3f(vx,vy,vz);
     
     tempRadius = innerRadius;
     vx= tempRadius * cos(start_angle);
     vy= centery+tempRadius * sin(start_angle);
     vz= thick;
     glVertex3f(vx,vy,vz);
     
     tempRadius = outRadius;
     vx= tempRadius * cos(start_angle);
     vy= centery + tempRadius * sin(start_angle);
     vz= thick;
     glVertex3f(vx,vy,vz);
     
     glEnd();
     
     //top square
     glBegin(GL_TRIANGLE_STRIP);
     
     tempRadius = outRadius;
     vx= tempRadius * cos(end_angle);
     vy= centery+ tempRadius * sin(end_angle);
     vz= -thick;
     glVertex3f(vx,vy,vz);
     
     tempRadius = innerRadius;
     vx= tempRadius * cos(end_angle);
     vy= centery+tempRadius * sin(end_angle);
     vz= -thick;
     glVertex3f(vx,vy,vz);
     
     tempRadius = outRadius;
     vx= tempRadius * cos(end_angle);
     vy= centery+tempRadius * sin(end_angle);
     vz= thick;
     glVertex3f(vx,vy,vz);
     
     tempRadius = innerRadius;
     vx= tempRadius * cos(end_angle);
     vy= centery+tempRadius * sin(end_angle);
     vz= thick;
     glVertex3f(vx,vy,vz);
     
     
     glEnd();
     
}

void draw3Dcircle(double radius,double thick){
     glColor3f(0.91, 0, 0.02);
     glPushMatrix();
     draw3DCurve(radius, 0, thick, 0, 2.1*pi,pi/180);
     glPopMatrix();
}




#pragma mark draw chars
void draw1(){
     glPushMatrix();
     
     glColor3f(1, 0.6, 0.8);
     //竖
     cube(0.25, 1.75, thick);
     
     glPopMatrix();
}

void draw2(){
     glColor3f(0.0f, 1.0f, 0.0f);
     
     //横
     glPushMatrix();
     glTranslatef(0,-1.25,0);
     cube(1, 0.25, thick);
     glPopMatrix();
     
     //斜着
     glPushMatrix();
     glTranslatef(-0.1,-0.4,0);
     glRotated(-38, 0, 0, 1);
     cube(0.25, 1.3, thick);
     glPopMatrix();
     
     if (DISPLAYMODE == 0) {
          glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
     }
     else if (DISPLAYMODE == 1){
          glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
     }
     
     double start_angle = 0;
     double end_angle = pi;
     
     //curve
     glPushMatrix();
     glTranslatef(-0.1, 0.4, 0);
     draw3DCurve(1, 1-2*thick, thick, start_angle, end_angle,pi/180);
     glPopMatrix();
     
}


void draw3(){
     
     glColor3f(0.0f, 0.0f, 0.0f);
     
     glPushMatrix();
     glTranslatef(0, 0.75, 0);
     draw3DCurve(outRadius, innerRadius, thick, - pi /2, pi * 3 / 4,pi/180);
     glPopMatrix();
     
     glPushMatrix();
     glTranslatef(0, -0.75, 0);
     
     draw3DCurve(outRadius, innerRadius, thick, -pi * 3/4, pi / 2,pi/180);
     glPopMatrix();
     
}

void draw4(){
     glPushMatrix();
     
     glColor3f(0.9f, 0.9f, 0.0f);
     
     //横
     glPushMatrix();
     glTranslatef(-0.5,-0.5,0);
     cube(1, 0.25, thick);
     glPopMatrix();
     
     //竖
     cube(0.25, 1.75, thick);
     
     //斜着
     glPushMatrix();
     glRotated(-30, 0, 0, 1);
     glTranslatef(-0.9,0.3,0);
     cube(0.25, 1.25, thick);
     glPopMatrix();
     
     glPopMatrix();
}

void draw5(){
     glColor3f(0.9f, 0.9f, 0.0f);
     
     glPushMatrix();
     glTranslatef(0, 1.5, 0);
     cube(1, 0.25, 0.25);
     glPopMatrix();
     
     glPushMatrix();
     glTranslatef(-0.75, 0.5, 0);
     cube(0.25, 0.75, 0.25);
     glPopMatrix();
     
     glPushMatrix();
     glTranslatef(-0, -0.75, 0);
     draw3DCurve(outRadius+0.25, innerRadius+0.25, thick, -pi*3/4, pi*3/4,pi/180);
     glPopMatrix();
}

void draw6(){
     glPushMatrix();
     glColor3f(0.51, 0.96, 0.09);
     
     glPushMatrix();
     glTranslatef(-0.25, 0.8, 0);
     glRotated(70, 0, 0, 1.0f);
     cube(1.5, 0.25, thick);
     glPopMatrix();
     
     glPushMatrix();
     glTranslatef(0, -0.75, 0);
     draw3DCurve(outRadius, innerRadius, thick, 0, 2.1*pi,pi/180);
     glPopMatrix();
     
     glPopMatrix();
}

void draw7(){
     glPushMatrix();
     
     glColor3f(0.53, 0.68, 0.96);
     
     glPushMatrix();
     glTranslatef(0.0f, 1.5f, 0.0f);
     cube(1, 0.25, thick);
     glPopMatrix();
     
     glPushMatrix();
     glTranslatef(0.26f, 0.0f, 0);
     glRotated(70, 0, 0, 1.0f);
     cube(1.5, 0.25, thick);
     glPopMatrix();
     
     glPopMatrix();
}

void draw8(){
     glPushMatrix();
     glColor3f(0.04, 0.49, 0.98);
     
     double start_angle= 0;
     double end_angle = 2.1*pi;
     
     glPushMatrix();
     glTranslatef(0, 0.75, 0);
     draw3DCurve(outRadius, innerRadius, thick, start_angle, end_angle,pi/180);
     glPopMatrix();
     
     glPushMatrix();
     glTranslatef(0, -0.75, 0);
     draw3DCurve(outRadius, innerRadius, thick, start_angle, end_angle,pi/180);
     glPopMatrix();
     
     glPopMatrix();
}

void draw9(){
     glPushMatrix();
     glColor3f(0.6, 0.2, 0.8);
     
     glPushMatrix();
     glTranslatef(0.25, -0.25, 0);
     glRotated(70, 0, 0, 1.0f);
     cube(1.5, 0.25, thick);
     glPopMatrix();
     
     glPushMatrix();
     glTranslatef(0, 1, 0);
     draw3DCurve(outRadius, innerRadius, thick, 0, 2.1*pi,pi/180);
     glPopMatrix();
     
     glPopMatrix();
}

void drawC(){
     glColor3f(0.61, 0.8, 0.3);
     glPushMatrix();
     draw3DCurve(outRadius+0.5, innerRadius+0.5, thick, pi / 4, pi * 7/4,pi/180);
     glPopMatrix();
}

void drawX(){
     double thick = 0.5f;
     glPushMatrix();
     glColor3f(0.61, 0.8, 0.3);
     glPushMatrix();
     glRotated(60, 0, 0, 1.0f);
     cube(1.5, 0.25, thick);
     glPopMatrix();
     
     glPushMatrix();
     glRotated(-60, 0, 0, 1.0f);
     cube(1.5, 0.25, thick);
     glPopMatrix();
     glPopMatrix();
}


void draw_char(char c){
     switch (c) {
          case '1':
               draw1();break;
               
          case '2':
               draw2();break;
               
          case '3':
               draw3();break;
               
          case '4':
               draw4();break;
               
          case '5':
               draw5();break;
               
          case '6':
               draw6();break;
               
          case '7':
               draw7();break;
               
          case '8':
               draw8();break;
               
          case '9':
               draw9();break;
               
          case 'X':
               drawX();break;
               
          case 'C':
               drawC();break;
               
          case '!':
               draw3Dcircle(1.5, thick);
               break;
               
          case '*':
               drawX();
               break;
               
          default:
               break;
     }
}


#pragma mark program lifecycle
void assgin1(){
     glPushMatrix();
     
     
     glPushMatrix();
     glTranslatef(-30, 0, 15);
     glRotated(clockwise, 0, 1, 0);
     glTranslatef(30, 0, -15);
     cubeWithString(-30, 0, 15, '!','*','X','C');
     glPopMatrix();
     
     glPushMatrix();
     glTranslatef(-15, 0, 5);
     glRotated(counterclockwise, 0, 1, 0);
     glTranslatef(15, 0, -5);
     cubeWithString(-15, 0, 5, '8','8','*','4');
     glPopMatrix();
     
     glPushMatrix();
     glRotated(clockwise, 0, 1,0);
     cubeWithString(0, 0, 0, '9','2','!','4');
     glPopMatrix();
     
     
     glPushMatrix();
     glTranslatef(15, 0, 5);
     glRotated(counterclockwise, 0, 1, 0);
     glTranslatef(-15, 0, -5);
     cubeWithString(15, 0, 5, '5','6','7','8');
     glPopMatrix();
     
     glPushMatrix();
     glTranslatef(30, 0, 15);
     glRotated(clockwise, 0, 1, 0);
     glTranslatef(-30, 0, -15);
     cubeWithString(30, 0, 15, '1','2','3','4');
     glPopMatrix();
     
     glPushMatrix();
     glTranslatef(0, 0, 20);
     draw3();
     
     glTranslatef(10, 0, 0);
     draw2();
     
     
     glPopMatrix();
     
     glPopMatrix();
}

void assgin2(){
     glPushMatrix();
     
     
     /* lighting */
     
     glEnable(GL_LIGHTING);
     {
          
          
          GLfloat lPos[]= {10,200,200,10};
          GLfloat lDif[]= {1,1,1,1};
          GLfloat lAmb[]= {.05,.05,.05,1};
          glLightfv(GL_LIGHT0, GL_DIFFUSE, lDif);
          glLightfv(GL_LIGHT0, GL_AMBIENT, lAmb);
          glLightfv(GL_LIGHT0, GL_POSITION,lPos);
          glEnable(GL_LIGHT0);
          
     }
     
     
     //draw 5 cubes
     glPushMatrix();
     glTranslatef(-15, 0, 10);
     glRotated(clockwise, 0, 1, 0);
     cubeWithString(0, 0, 0, '!','!','!','!');
     glPopMatrix();
     
     glPushMatrix();
     glTranslatef(-8, 0, 5);
     glRotated(counterclockwise, 0, 1, 0);
     cubeWithString(0, 0, 0, '6','6','6','6');
     glPopMatrix();
     
     glPushMatrix();
     glRotated(clockwise, 0, 1,0);
     cubeWithString(0, 0, 0, '2','2','2','2');
     glPopMatrix();
     
     
     glPushMatrix();
     glTranslatef(8, 0, 5);
     glRotated(counterclockwise, 0, 1, 0);
     cubeWithString(0, 0, 0, '5','5','5','5');
     glPopMatrix();
     
     glPushMatrix();
     glTranslatef(15, 0, 10);
     glRotated(clockwise, 0, 1, 0);
     cubeWithString(0, 0, 0, 'c','c','c','c');
     glPopMatrix();
     
//     //draw strings
//     glPushMatrix();
//     glTranslatef(movex + 5, 0, movez);
//     draw_char(numcount+49);
//     glPopMatrix();
     
     glPopMatrix();
}

void display(){
     
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     glClearColor(1, 1, 1, 0);
     glMatrixMode(GL_MODELVIEW);
     glLoadIdentity();

     //set camera
     GLfloat position[] = {10,10,15,0};
     glLightfv(GL_LIGHT0, GL_POSITION, position);
     
     //eye,center,up
     gluLookAt(ex, ey, ez, 0, 0, 0, 0, 1, 0);
     assgin2();
     glutSwapBuffers();
}



//when window shape changes
void reshape(int w, int h){
     glMatrixMode(GL_PROJECTION);
     gluPerspective(60, h/(float)w, .1, 100);
     glViewport(w/2,h/2+2000, w, h);
     glMatrixMode(GL_MODELVIEW);
     g_width=w;
     g_height=h;
}

//rotate eye
void idle(){
     glutPostRedisplay();
     clockwise += 1;
     counterclockwise -= 1;
     if (movez < 20) {
          movez += 0.25;
          movex -= 0.125;
     }
     else{
          movex = 0;
          movez = 0;
          numcount = numcount < 9 ? numcount+1 : 0;
     }
     display();
     reshape(500, 500);
}

//minitor keyboard activity
void keyboard(unsigned char k, int x, int y){
     switch(k){
          case 27:
          case 'q':
          case 'Q':
               exit(0);
     }
}


//on mouse click
void mouse(int button, int state, int x, int y)
{
     if(state==GLUT_DOWN) //第一次鼠标按下时,记录鼠标在窗口中的初始坐标
          oldmx=x,oldmy=y;
}

//on mouse movement
void onMouseMove(int x,int y) //处理鼠标拖动
{
     du +=x-oldmx; //鼠标在窗口x轴方向上的增量加到视点绕y轴的角度上，这样就左右转了
     ey +=(y-oldmy); //鼠标在窗口y轴方向上的改变加到视点的y坐标上，就上下转了
     
     ex = r * cos(c*du);
     ez = r * sin(c*du);
     
     oldmx=x,oldmy=y; //把此时的鼠标坐标作为旧值，为下一次计算增量做准备
}


//load TGA texture
//bool LoadTGA(TextureImage *texture, char *filename)			// Loads A TGA File Into Memory
//{
//     GLubyte		TGAheader[12]={0,0,2,0,0,0,0,0,0,0,0,0};	// Uncompressed TGA Header
//     GLubyte		TGAcompare[12];								// Used To Compare TGA Header
//     GLubyte		header[6];									// First 6 Useful Bytes From The Header
//     GLuint		bytesPerPixel;								// Holds Number Of Bytes Per Pixel Used In The TGA File
//     GLuint		imageSize;									// Used To Store The Image Size When Setting Aside Ram
//     GLuint		temp;										// Temporary Variable
//     GLuint		type=GL_RGBA;								// Set The Default GL Mode To RBGA (32 BPP)
//     
//     FILE *file = fopen(filename, "rb");						// Open The TGA File
//     
//     if(	file==NULL ||										// Does File Even Exist?
//        fread(TGAcompare,1,sizeof(TGAcompare),file)!=sizeof(TGAcompare) ||	// Are There 12 Bytes To Read?
//        memcmp(TGAheader,TGAcompare,sizeof(TGAheader))!=0				||	// Does The Header Match What We Want?
//        fread(header,1,sizeof(header),file)!=sizeof(header))				// If So Read Next 6 Header Bytes
//     {
//          if (file == NULL)									// Did The File Even Exist? *Added Jim Strong*
//               return false;									// Return False
//          else
//          {
//               fclose(file);									// If Anything Failed, Close The File
//               return false;									// Return False
//          }
//     }
//     
//     texture->width  = header[1] * 256 + header[0];			// Determine The TGA Width	(highbyte*256+lowbyte)
//     texture->height = header[3] * 256 + header[2];			// Determine The TGA Height	(highbyte*256+lowbyte)
//     
//     //OpenGL中纹理只能使用24位或者32位的TGA图像
//     if(	texture->width	<=0	||								// Is The Width Less Than Or Equal To Zero
//        texture->height	<=0	||								// Is The Height Less Than Or Equal To Zero
//        (header[4]!=24 && header[4]!=32))					// Is The TGA 24 or 32 Bit?
//     {
//          fclose(file);										// If Anything Failed, Close The File
//          return false;										// Return False
//     }
//     
//     texture->bpp	= header[4];							// Grab The TGA's Bits Per Pixel (24 or 32)
//     bytesPerPixel	= texture->bpp/8;						// Divide By 8 To Get The Bytes Per Pixel
//     imageSize		= texture->width*texture->height*bytesPerPixel;	// Calculate The Memory Required For The TGA Data
//     
//     texture->imageData=(GLubyte *)malloc(imageSize);		// Reserve Memory To Hold The TGA Data
//     
//     if(	texture->imageData==NULL ||							// Does The Storage Memory Exist?
//        fread(texture->imageData, 1, imageSize, file)!=imageSize)	// Does The Image Size Match The Memory Reserved?
//     {
//          if(texture->imageData!=NULL)						// Was Image Data Loaded
//               free(texture->imageData);						// If So, Release The Image Data
//          
//          fclose(file);										// Close The File
//          return false;										// Return False
//     }
//     
//     //RGB数据格式转换，便于在OpenGL中使用
//     for(GLuint i=0; i<int(imageSize); i+=bytesPerPixel)		// Loop Through The Image Data
//     {														// Swaps The 1st And 3rd Bytes ('R'ed and 'B'lue)
//          temp=texture->imageData[i];							// Temporarily Store The Value At Image Data 'i'
//          texture->imageData[i] = texture->imageData[i + 2];	// Set The 1st Byte To The Value Of The 3rd Byte
//          texture->imageData[i + 2] = temp;					// Set The 3rd Byte To The Value In 'temp' (1st Byte Value)
//     }
//     
//     fclose (file);											// Close The File
//     
//     // Build A Texture From The Data
//     glGenTextures(1, &texture[0].texID);					// Generate OpenGL texture IDs
//     
//     glBindTexture(GL_TEXTURE_2D, texture[0].texID);			// Bind Our Texture
//     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);	// Linear Filtered
//     
//     if (texture[0].bpp==24)									// Was The TGA 24 Bits
//     {
//          type=GL_RGB;										// If So Set The 'type' To GL_RGB
//     }
//     
//     glTexImage2D(GL_TEXTURE_2D, 0, type, texture[0].width, texture[0].height, 0, type, GL_UNSIGNED_BYTE, texture[0].imageData);
//     
//     return true;											// Texture Building Went Ok, Return True
//}

//void loadTexture(){
//     
//     if(!LoadTGA(&tex,"/Users/chenxu/desktop/floor.tga"))
//          return;
//     glColorMaterial(GL_FRONT,GL_AMBIENT_AND_DIFFUSE);
//     glEnable(GL_COLOR_MATERIAL);
//     glClearColor(0.0f,0.0f,0.0f,0.5f);
//     glClearDepth(1.0f);
//     glDepthFunc(GL_LEQUAL);
//     glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
//     glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
//     glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
//     glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
//     glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
//}



int main(int argc, char ** argv){
     g_width = 500;
     g_height = 500;
     
     glutInit(&argc, argv);
     glutInitDisplayMode(GLUT_RGB |GLUT_DOUBLE |GLUT_DEPTH);
     glutInitWindowPosition(200,200);
     glutInitWindowSize(g_width, g_height);
     glutCreateWindow("Cmpsc 180 project part 1");
     

     //loadTexture();
     glutDisplayFunc(display);
     glutReshapeFunc(reshape);

     glutKeyboardFunc(keyboard);
     glutMouseFunc(mouse);        //mouse click
     glutMotionFunc(onMouseMove); //mouse movement
     
     glEnable(GL_DEPTH_TEST);
     glShadeModel(GL_SMOOTH);
     
     
     glutIdleFunc(idle);
     glutMainLoop();
     
     return 0;
}
